package com.meilai.project.service.business.installOrder.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.dto.business.installOrder.WorkOrderReportInfoDTO;
import com.meilai.project.entity.business.installOrder.ManyWorkOrderReport;
import com.meilai.project.entity.business.installOrder.WorkOrderReportRelation;
import com.meilai.project.mapper.business.installOrder.ManyWorkOrderReportMapper;
import com.meilai.project.mapper.business.installOrder.WorkOrderMapper;
import com.meilai.project.service.business.installOrder.ManyWorkOrderReportService;
import com.meilai.project.service.business.installOrder.WorkOrderReportRelationService;
import com.meilai.project.service.middleware.AttachmentService;
import com.meilai.project.util.FileUtil;
import com.meilai.project.util.ppt.NewExportPPTUtil;
import com.meilai.project.vo.business.installOrder.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 多工单导出报告表 服务实现类
 * </p>
 *
 * @author xhy
 * @since 2022-08-03
 */
@Service
@Log4j2
public class ManyWorkOrderReportImpl extends ServiceImpl<ManyWorkOrderReportMapper, ManyWorkOrderReport> implements ManyWorkOrderReportService {

    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    @Value("${spring.profiles.active}")
    private String evn;
    @Value("${static-resource.file-space}")
    private String FILE_SPACE;
    @Autowired
    private NewExportPPTUtil newExportPPTUtil;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private WorkOrderMapper workOrderMapper;

    @Autowired
    private WorkOrderReportRelationService workOrderReportRelationService;

    @Override
    public void generateReport(WorkOrderReportInfoDTO data) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        boolean needCompress = false; // 是否压缩
        // 创建数据 设置在生成状态
        ManyWorkOrderReport manyWorkOrderReport = new ManyWorkOrderReport();
        if (data.getMany_report_id() != null) {
            manyWorkOrderReport.setId(data.getMany_report_id());
        }
        manyWorkOrderReport.setReport_can_download(0);
        manyWorkOrderReport.setReport_path(null);
        manyWorkOrderReport.setCreated_at(LocalDateTime.now());
        this.saveOrUpdate(manyWorkOrderReport);
        workOrderReportRelationService.remove(Wrappers.<WorkOrderReportRelation>lambdaQuery().eq(WorkOrderReportRelation::getMany_work_order_report_id, manyWorkOrderReport.getId()));
        workOrderReportRelationService.saveBatch(data.getIds().stream().map(item -> {
            WorkOrderReportRelation reportRelation = new WorkOrderReportRelation();
            reportRelation.setWork_order_id(item);
            reportRelation.setMany_work_order_report_id(manyWorkOrderReport.getId());
            return reportRelation;
        }).collect(Collectors.toList()));
        try {
            data.setCreate_time(dtf2.format(LocalDateTime.now()));
            // 修改为集合
            data.setCount(workOrderMapper.getWorkOrderPassedNumByIds(data.getIds()));
            // 修改为集合
            handleReportBuildingVO(data, workOrderMapper.getWorkOrderReportBuildingVOsByIds(data.getIds()));
            // 修改为集合
            handleReportPointPhotoVO(data, workOrderMapper.getPointPhotosByIds(data.getIds(), data.getPer_device_one_photo()));
            String fileName = data.getFile_name() + "_" + dtf.format(LocalDateTime.now()) + ".pptx";
            log.info("生成报告数参数，{}", JSON.toJSONString(data));
            String localPath = "";
            if (data.getReport_type() == 1) {
                localPath = newExportPPTUtil.genWorkOrderReport(data, FILE_SPACE + File.separator + "ppt_mother_01.pptx", FILE_SPACE, fileName);
            } else {
                localPath = newExportPPTUtil.genWorkOrderReport2(data, FILE_SPACE + File.separator + "ppt_mother_01.pptx", FILE_SPACE, fileName);
            }
//            String localPath = newExportPPTUtil.genWorkOrderReport2(data, FILE_SPACE + File.separator + "ppt_mother_01.pptx", FILE_SPACE, fileName);
            log.info("ppt已保存至本地" + localPath);
            //如果是在生产环境，则压缩至zip，然后上传至oss，然后将本地文件删除
            if (evn.equals("prod")) {
                log.info("生产环境");
                File pptFile = new File(localPath);
                List<File> list = new ArrayList<>();
                list.add(pptFile);
                String tmpZipFilePath = "";
                String url = "";

                log.info("判断是否压缩");
                try {
                    MultipartFile multipartFile = null;
                    if (needCompress) {
                        log.info("压缩");
                        tmpZipFilePath = FileUtil.zipFile(list, fileName);
                        File tempZipfile = new File(tmpZipFilePath);
                        FileInputStream input = new FileInputStream(tempZipfile);
                        multipartFile = new MockMultipartFile("file", tempZipfile.getName(), "application/x-zip-compressed", IOUtils.toByteArray(input));
                        url = attachmentService.store2("", multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), fileName + ".zip");
                        FileUtil.delFile(tmpZipFilePath);
                        log.info("zip已上传至oss," + url);
                    } else {
                        log.info("不压缩");
                        FileInputStream input = new FileInputStream(pptFile);
                        multipartFile = new MockMultipartFile("file", pptFile.getName(), "application/vnd.openxmlformats-officedocument.presentationml.template", IOUtils.toByteArray(input));
                        url = attachmentService.store2("master", multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), fileName + ".pptx");
                        log.info("pptx已上传至oss," + url);
                    }
                    // 记录路径保存
                    manyWorkOrderReport.setReport_can_download(1);
                    manyWorkOrderReport.setReport_path(url);
                    this.updateById(manyWorkOrderReport);
                    log.info("上传完成");
                } catch (Exception e) {
                    log.info("出错");
                    e.printStackTrace();
                    log.error(e);
                }
                try {
                    FileUtil.delFile(localPath);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error(e);
                }
            } else {
                log.info("开发环境");
                //如果是在开发环境，则不上传至oss，本地文件不删除
                // 记录路径
                manyWorkOrderReport.setReport_can_download(1);
                manyWorkOrderReport.setReport_path(localPath);
                this.updateById(manyWorkOrderReport);
            }
        } catch (Exception e) {
            e.printStackTrace();
            manyWorkOrderReport.setReport_can_download(2);
            manyWorkOrderReport.setReport_path(null);
            this.updateById(manyWorkOrderReport);
        }
    }

    private void handleReportBuildingVO(WorkOrderReportInfoDTO dto, List<WorkOrderReportDetailByBuildingVO> list) {
        List<WorkOrderReportDetailByBuildingVO> resultList = new ArrayList<>();
        TreeMap<Long, String> pointTypeIdMap = new TreeMap<Long, String>();
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(item -> {
                Long point_type_id = item.getPoint_type_id();
                pointTypeIdMap.putIfAbsent(point_type_id, item.getPoint_type());
            });
            if (pointTypeIdMap.size() == 1) {
                resultList = list.stream().peek(item -> {
                    Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = new HashMap<>();
                    counts.put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                    item.setCounts(counts);
                }).collect(Collectors.toList());
            } else if (pointTypeIdMap.size() > 1) {
                Map<String, WorkOrderReportDetailByBuildingVO> voMap = new TreeMap<>();
                list.forEach(item -> {
                    String key = item.getDaterange() + "_" + item.getBuilding_area_id();
                    WorkOrderReportDetailByBuildingVO temp = null;
                    if (voMap.get(key) == null) {
                        Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = new HashMap<>();
                        counts.put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                        temp = new WorkOrderReportDetailByBuildingVO();
                        BeanUtils.copyProperties(item, temp);
                        temp.setCounts(counts);
                    } else {
                        temp = voMap.get(key);
                        temp.getCounts().put(item.getPoint_type_id(), new WorkOrderReportDetailByBuildingInnerVO(item.getPoint_type(), (item.getCount() == 0 ? "" : item.getCount().toString())));
                    }
                    voMap.put(key, temp);
                });
                //这里将map.entrySet()转换成list
                List<Map.Entry<String, WorkOrderReportDetailByBuildingVO>> tempList = new ArrayList<Map.Entry<String, WorkOrderReportDetailByBuildingVO>>(voMap.entrySet());
                //然后通过比较器来实现排序
                tempList.sort(new Comparator<Map.Entry<String, WorkOrderReportDetailByBuildingVO>>() {
                    @Override
                    public int compare(Map.Entry<String, WorkOrderReportDetailByBuildingVO> o1, Map.Entry<String, WorkOrderReportDetailByBuildingVO> o2) {
                        return o1.getValue().getBuilding_area_id().compareTo(o2.getValue().getBuilding_area_id());
                    }
                });
                for (Map.Entry<String, WorkOrderReportDetailByBuildingVO> mapping : tempList) {
                    resultList.add(mapping.getValue());
                }
            }
        }

        String[] bHeaders = dto.getBuildingTableHeader();
        String[] temp = new String[pointTypeIdMap.size()];
        int k = 0;
        for (String value : pointTypeIdMap.values()) {
            temp[k] = value;
            k++;
        }
        dto.setBuildingTableHeader(ArrayUtils.addAll(bHeaders, temp));
        if (CollectionUtils.isNotEmpty(resultList)) {
            String[][] bDatas = new String[resultList.size()][4 + pointTypeIdMap.size()];
            for (int i = 0; i < resultList.size(); i++) {
                WorkOrderReportDetailByBuildingVO item = resultList.get(i);
                String[] row = {Integer.toString(i + 1), item.getBuilding_area(), item.getBuilding_area_address(), item.getDaterange()};
                String[] rowCount = new String[pointTypeIdMap.size()];
                Map<Long, WorkOrderReportDetailByBuildingInnerVO> counts = item.getCounts();
                if (counts != null && counts.size() > 0) {
                    int m = 0;
                    for (Long key : pointTypeIdMap.keySet()) {
                        rowCount[m] = (counts.get(key) != null && counts.get(key).getCount() != null) ? counts.get(key).getCount().toString() : "";
                        m++;
                    }
                }
                bDatas[i] = ArrayUtils.addAll(row, rowCount);
            }
            dto.setBuildingTableData(bDatas);
        } else {
            dto.setBuildingTableData(null);
        }

    }

    private void handleReportPointPhotoVO(WorkOrderReportInfoDTO dto, List<WorkOrderReportPhotoVO> originList) {
        if (CollectionUtils.isNotEmpty(originList)) {
            List<WorkOrderReportPhotoReformVO> resultList = new ArrayList<>();
            TreeMap<Long, WorkOrderReportPhotoReformVO> buildingMap = new TreeMap<>();
            HashMap<Long, List<WorkOrderReportPhotoReformDateRangeVO>> daterangeMap = new HashMap<>();
            HashMap<String, List<WorkOrderReportPhotoReformInnerVO>> pointMap = new HashMap<>();
            HashMap<Long, Set<String>> pointCountMap = new HashMap<>();

            for (WorkOrderReportPhotoVO item : originList) {
                Long key = item.getBuilding_area_id();
                if (key == null) continue;

                // 楼盘信息
                WorkOrderReportPhotoReformVO building = new WorkOrderReportPhotoReformVO();
                BeanUtils.copyProperties(item, building);
                building.getDateranges().add(building.getDaterange());
                buildingMap.putIfAbsent(key, building);

                // 时间段信息
                if (CollectionUtils.isNotEmpty(building.getDateranges())) {
                    for (String daterange : building.getDateranges()) {
                        List<WorkOrderReportPhotoReformDateRangeVO> daterangeSet = daterangeMap.get(key);
                        if (daterangeSet == null) {
                            daterangeSet = new ArrayList<>();
                        }
                        boolean isExist = false;
                        for (WorkOrderReportPhotoReformDateRangeVO vo : daterangeSet) {
                            if (vo.getDaterange().equals(daterange)) {
                                isExist = true;
                                break;
                            }
                        }
                        if (!isExist) {
                            WorkOrderReportPhotoReformDateRangeVO dateRangeVO = new WorkOrderReportPhotoReformDateRangeVO();
                            dateRangeVO.setBuilding_area_id(key);
                            dateRangeVO.setDaterange(daterange);
                            daterangeSet.add(dateRangeVO);
                        }
                        daterangeMap.putIfAbsent(key, daterangeSet);
                    }
                }

                // 点位信息
                String key2 = key + "_" + building.getDaterange();
                List<WorkOrderReportPhotoReformInnerVO> points = pointMap.get(key2);
                if (points == null) {
                    points = new ArrayList<>();
                }
                WorkOrderReportPhotoReformInnerVO point = new WorkOrderReportPhotoReformInnerVO();
                BeanUtils.copyProperties(item, point);
                points.add(point);
                pointMap.put(key2, points);

                // 点位数量
                Set<String> pointCounts = pointCountMap.get(key);
                if (pointCounts == null) {
                    pointCounts = new HashSet<String>();
                }
                pointCounts.add(item.getId().toString());
                pointCountMap.putIfAbsent(key, pointCounts);
            }

            int pointIdx = 0;
            Long prevBuildingAreaId = 0L;
            Long prevPointAuditId = 0L;
            if (buildingMap.size() > 0) {
                for (Map.Entry<Long, WorkOrderReportPhotoReformVO> mapping : buildingMap.entrySet()) {
                    WorkOrderReportPhotoReformVO curBuild = mapping.getValue();
                    List<WorkOrderReportPhotoReformDateRangeVO> daterangeSet = daterangeMap.get(mapping.getKey());
                    if (CollectionUtils.isNotEmpty(daterangeSet)) {
                        for (WorkOrderReportPhotoReformDateRangeVO daterangevo : daterangeSet) {
                            String key2 = mapping.getKey() + "_" + daterangevo.getDaterange();
                            List<WorkOrderReportPhotoReformInnerVO> curPoints = pointMap.get(key2);
                            if (CollectionUtils.isNotEmpty(curPoints)) {
                                curPoints.sort((WorkOrderReportPhotoReformInnerVO b1, WorkOrderReportPhotoReformInnerVO b2) -> b2.getId().compareTo(b1.getId()));
                                for (WorkOrderReportPhotoReformInnerVO p : curPoints) {
                                    if (!p.getBuilding_area_id().equals(prevBuildingAreaId)) {
                                        prevBuildingAreaId = p.getBuilding_area_id();
                                        pointIdx = 0;
                                    }
                                    if (!p.getId().equals(prevPointAuditId)) {
                                        prevPointAuditId = p.getId();
                                        pointIdx++;
                                    }
                                    p.setIdx(String.valueOf(pointIdx));
                                }
                                daterangevo.setPoints(curPoints);
                            }
                        }
                        curBuild.setDaterangeVOs(daterangeSet);
                    }
                    Set<String> countSet = pointCountMap.get(mapping.getKey());
                    curBuild.setCount(countSet.size());
                    resultList.add(curBuild);
                }
            }
            dto.setPhotos(resultList.size() > 0 ? resultList : new ArrayList<>());
        }
    }

    @Override
    public Page<ManyWorkOrderReportVO> page(Integer current_page, Integer page_size, Long order_id) {
        Page<ManyWorkOrderReportVO> page = new Page<>(current_page, page_size);
        List<Long> ids;
        if (order_id != null) {
            ids = baseMapper.getIds(order_id);
            if (CollectionUtils.isEmpty(ids)) {
                ids.add(-1L);
            }
        } else {
            ids = new ArrayList<>();
        }
        List<ManyWorkOrderReportVO> list = baseMapper.selectPage(page, ids);
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> collect = list.stream().map(ManyWorkOrderReport::getId).collect(Collectors.toList());
            List<WorkOrderReportRelation> relationList = workOrderReportRelationService.list(Wrappers.<WorkOrderReportRelation>lambdaQuery().in(WorkOrderReportRelation::getMany_work_order_report_id, collect));
            List<Long> work_order_ids = relationList.stream().map(WorkOrderReportRelation::getWork_order_id).distinct().collect(Collectors.toList());
            List<WorkOrderVO> orderList = workOrderMapper.selectListVoByIds(work_order_ids);
            Map<Long, List<WorkOrderVO>> orderMap = orderList.stream().collect(Collectors.groupingBy(WorkOrderVO::getId));
            Map<Long, List<WorkOrderReportRelation>> relationMap = relationList.stream().collect(Collectors.groupingBy(WorkOrderReportRelation::getMany_work_order_report_id));
            list.forEach(item -> {
                item.setWork_order_list(new ArrayList<>());
                if (relationMap.containsKey(item.getId())) {
                    relationMap.get(item.getId()).forEach(tmp -> {
                        if (orderMap.containsKey(tmp.getWork_order_id())) {
                            item.getWork_order_list().add(orderMap.get(tmp.getWork_order_id()).get(0));
                        }
                    });
                }
            });
        }
        page.setRecords(list);
        return page;
    }
}
